//1.rust通过所有权机制来管理内存，编译器在编译就会根据所有权规则对内存的使用进行检查
//
//2.堆和栈
//      编译的时候数据的类型大小是固定的，就是分配在栈上的
//      编译的时候数据的类型大小不是固定的，就是分配在堆上的
//
//3.作用域:{}
//
//
fn main() {
    let x:i32 = 1;
    {
        let y:i32 = 1;// 定义在栈上
        println!("x = {}", x);
        println!("y = {}", y);

    }

    {
        let mut s1 = String::from("hello"); // 定义在堆上
        s1.push_str(" world");                                
        println!("s1 = {}", s1);// String 类型离开作用域的时候会调用drop方法

        let s2 = s1;
        println!("s2 = {}", s2);
        // println!("s1 = {}", s1);// move to s2, s1 invalid


        // clone 深拷贝
        let s3 = s2.clone();
        println!("s3 = {}", s3); 
        println!("s2 = {}", s2); 


    }


    // copy 栈的赋值，与堆上的赋值不同
    // 如果实现了 copy trait 特征, 那么原来的还是可以使用的
    let a = 1;
    let b = a;
    println!("a = {}, b = {}", a, b);
    // 常用的具有copy trait：
    //      所有的整型
    //      浮点型
    //      布尔型
    //      字符类型 char
    //      元组



    println!("Hello, world!");
}
